﻿// No word splitting is allowed, thus all the following methods are for research IDEAS only
///////////////////////////////////////////////////////////////////////////////////////////
// ٦_١١٥	وتمت كلمت ربك صدقا وعدلا لا مبدل لكلمته وهو السميع العليم
// 6:115	And the Words of your Lord has been prefected full of Truth and Justice:
//          None can change His Words, and He is the All-hearing, All-knowing.
///////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;

using DigitalQuran.Collection;
using DigitalQuran.Extensions;
using DigitalQuran.Numerology;
using DigitalQuran.IO;

using WavMaker;

namespace DigitalQuran.Research
{
    public static class SoundResearch
    {        
        [ResearchMethod()]
        public static void ChapterVersesSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters)
                values.Add(chapter.Verses.Count);            
            
            DoSaveAndPlayWAVFile(agent, agent.Client.Numerology.ActiveSystem.ToString() + "_ChapterVerses", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void ChapterWordsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters)
                values.Add(chapter.Verses.WordCount);            
            
            DoSaveAndPlayWAVFile(agent, "_ChapterWords", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void ChapterLettersSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters)
                values.Add(chapter.Verses.LetterCount);

            DoSaveAndPlayWAVFile(agent, "_ChapterLetters", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void ChapterValuesSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters)
                values.Add(chapter.Value);

            DoSaveAndPlayWAVFile(agent, "_ChapterValues", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        private static void ChapterValueDiffsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters)
                values.Add(chapter.Value);            

            List<long> valueDiffs = new List<long>();
            for (int i = 0; i < values.Count - 1; i++)                            
                valueDiffs.Add(values[i + 1] - values[i]);            
            
            DoSaveAndPlayWAVFile(agent, "_ChapterValueDiffs", valueDiffs, fequency);

            values.Clear();
            valueDiffs.Clear();
        }

        [ResearchMethod()]
        public static void VerseWordsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
                values.Add(verse.Words.Count);

            DoSaveAndPlayWAVFile(agent, "_VerseWords", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void VerseLettersSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
                values.Add(verse.Words.LetterCount);

            DoSaveAndPlayWAVFile(agent, "_VerseLetters", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void VerseValuesSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
                values.Add(verse.Value);

            DoSaveAndPlayWAVFile(agent, "_VerseValues", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        private static void VerseValueDiffsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
                values.Add(verse.Value);            

            List<long> valueDiffs = new List<long>();
            for (int i = 0; i < values.Count - 1; i++)                            
                valueDiffs.Add(values[i + 1] - values[i]);            
            
            DoSaveAndPlayWAVFile(agent, "_VerseValueDiffs", valueDiffs, fequency);

            values.Clear();
            valueDiffs.Clear();
        }

        [ResearchMethod()]
        public static void WordLettersSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
            {
                foreach (Word word in verse.Words)                
                    values.Add(word.Letters.Count);                
            }

            DoSaveAndPlayWAVFile(agent, "_WordLetters", values, fequency);

            values.Clear();
        }

        [ResearchMethod()]
        public static void WordValuesSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
            {
                foreach (Word word in verse.Words)                
                    values.Add(agent.Client.Numerology.CalculateValue(word));
            }

            DoSaveAndPlayWAVFile(agent, "_WordValues", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        private static void WordValueDiffsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
            {
                foreach (Word word in verse.Words)                
                    values.Add(agent.Client.Numerology.CalculateValue(word));                
            }

            List<long> valueDiffs = new List<long>();
            for (int i = 0; i < values.Count - 1; i++)
                valueDiffs.Add(values[i + 1] - values[i]);

            DoSaveAndPlayWAVFile(agent, "_WordValueDiffs", valueDiffs, fequency);

            values.Clear();
            valueDiffs.Clear();
        }

        [ResearchMethod()]
        public static void LetterValuesSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
            {
                for (int w = 0; w < verse.Words.Count; w++)                
                    for (int l = 0; l < verse.Words[w].ToString(agent.Client.ActiveTextMode).Length; l++)                    
                        values.Add(agent.Client.Numerology.CalculateValue(verse, w, l));                
            }

            DoSaveAndPlayWAVFile(agent, "_LetterValues", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        public static void LetterValueDiffsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses)
            {
                for (int w = 0; w < verse.Words.Count; w++)                
                    for (int l = 0; l < verse.Words[w].ToString(agent.Client.ActiveTextMode).Length; l++)                    
                        values.Add(agent.Client.Numerology.CalculateValue(verse, w, l));                                    
            }

            List<long> valueDiffs = new List<long>();
            for (int i = 0; i < values.Count - 1; i++)            
                valueDiffs.Add(values[i + 1] - values[i]);

            DoSaveAndPlayWAVFile(agent, "_LetterValueDiffs", valueDiffs, fequency);

            values.Clear();
            valueDiffs.Clear();
        }

        [ResearchMethod(Edition.Research)]
        public static void SameLetterGapsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            StringBuilder str = new StringBuilder();
            foreach (Verse verse in agent.Client.Selection.Verses)
                str.Append(verse.ToString(agent.Client.ActiveTextMode));            

            str.Replace("\r", "").Replace("\n", "").Replace(" ", "");

            int count = str.Length;
            List<long> values = new List<long>(count);

            for (int i = 0; i < count; i++)
            {
                bool found = false;
                for (int j = i + 1; j < count; j++)
                {
                    if (str[j] == str[i])
                    {
                        values.Add(j - i);
                        found = true;
                        break; // j
                    }
                }
                if (!found) // round roubin
                {
                    for (int j = 0; j < i + 1; j++)
                    {
                        if (str[j] == str[i])
                        {
                            values.Add(j - i + count);
                            found = true;
                            break; // j
                        }
                    }
                }
                if (!found) // unique letter                
                    values.Add(0);                
            }

            DoSaveAndPlayWAVFile(agent, "_SameLetterGaps", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        public static void SameLetterBackwardGapsSound(ResearchAgent agent, int fequency = Globals.DefaultFrequency)
        {            
            StringBuilder str = new StringBuilder();
            foreach (Verse verse in agent.Client.Selection.Verses)
                str.Append(verse.ToString(agent.Client.ActiveTextMode));            

            str.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            int count = str.Length;
            List<long> values = new List<long>(count);

            for (int i = 0; i < count; i++)
            {
                bool found = false;
                for (int j = i - 1; j >= 0; j--)
                {
                    if (str[j] == str[i])
                    {
                        values.Add(-j + i);
                        found = true;
                        break; // j
                    }
                }
                if (!found) // round roubin
                {
                    for (int j = count - 1; j > i; j--)
                    {
                        if (str[j] == str[i])
                        {
                            values.Add(-j + i + count);
                            found = true;
                            break; // j
                        }
                    }
                }
                if (!found) // unique letter
                    values.Add(0);
            }

            DoSaveAndPlayWAVFile(agent, "_SameLetterBackwardGaps", values, fequency);

            values.Clear();
        }

        [ResearchMethod(Edition.Research)]
        public static void PrimeVerseNumbers(ResearchAgent agent, int fequency = Globals.DefaultFrequency) {
            if (agent == null) return;
            
            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses) {
                if (verse.NumberInChapter.IsPrime()) {
                    values.Add(verse.NumberInChapter);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_PrimeVerseNumbers", values, fequency);
        }

        [ResearchMethod(Edition.Research)]
        public static void CompositeVerseNumbers(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;

            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses) {
                if (verse.NumberInChapter.IsComposite()) {
                    values.Add(verse.NumberInChapter);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_CompositeVerseNumbers", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        public static void PrimeChapterPlusVerses(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;

            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters) {
                int sum = chapter.GlobalNumber + chapter.Verses.Count;
                if (sum.IsPrime()) {
                    values.Add(sum);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_PrimeChapterPlusVerses", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        public static void CompositeChapterPlusVerses(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;

            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters) {
                int sum = chapter.GlobalNumber + chapter.Verses.Count;
                if (sum.IsComposite()) {
                    values.Add(sum);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_CompositeChapterPlusVerses", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        private static void DigitsInChapterNumbers(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;
            
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters) {
                values.Add(chapter.GlobalNumber.DigitCount());                
            }

            DoSaveAndPlayWAVFile(agent, "_DigitsInChapterNumbers", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        private static void DigitsInVerseNumbers(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;

            List<long> values = new List<long>();
            foreach (Verse verse in agent.Client.Selection.Verses) {
                values.Add(verse.NumberInChapter.DigitCount());                
            }

            DoSaveAndPlayWAVFile(agent, "_DigitsInVerseNumbers", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        private static void DigitsInPrimeChapterPlusVerses(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;

            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters) {
                int digits = chapter.GlobalNumber.DigitCount();
                foreach (Verse verse in chapter.Verses) {
                    digits += verse.NumberInChapter.DigitCount();
                }
                if (digits.IsPrime()) {
                    values.Add(digits);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_DigitsInPrimeChapterPlusVerses", values, frequency);
        }

        [ResearchMethod(Edition.Research)]
        private static void DigitsInCompositeChapterPlusVerses(ResearchAgent agent, int frequency = Globals.DefaultFrequency) {
            if (agent == null) return;
            
            List<long> values = new List<long>();
            foreach (Chapter chapter in agent.Client.Selection.Chapters) {
                int digits = chapter.GlobalNumber.DigitCount();
                foreach (Verse verse in chapter.Verses) {
                    digits += verse.NumberInChapter.DigitCount();
                }
                if (digits.IsComposite()) {
                    values.Add(digits);
                } else {
                    values.Add(0);
                }
            }

            DoSaveAndPlayWAVFile(agent, "_DigitsInCompositeChapterPlusVerses", values, frequency);
        }

        private static void DoSaveAndPlayWAVFile(ResearchAgent agent, string path, List<long> values, int fequency)
        {
            path = agent.Client.Numerology.ActiveSystem.ToString() + path;
            agent.SaveValues(path, values);
            WAVFile.GenerateWAVFile(ref path, values, fequency);
        }
    }
}